package com.boom.springapp.javafxdemo.utils;

import com.boom.springapp.javafxdemo.common.Comment;
import com.boom.springapp.javafxdemo.common.DefaultConfiguration;
import com.boom.springapp.javafxdemo.common.Picture;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opencsv.CSVWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 评论数据保存到CSV文件的工具类
 */
@Component
public class CommentCsvSaver {
    
    private static final Logger logger = LoggerFactory.getLogger(CommentCsvSaver.class);
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final ImageDownloader imageDownloader;
    private final DefaultConfiguration defaultConfiguration;
    
    public CommentCsvSaver(ImageDownloader imageDownloader, DefaultConfiguration defaultConfiguration) {
        this.imageDownloader = imageDownloader;
        this.defaultConfiguration = defaultConfiguration;
    }
    
    /**
     * 将评论对象转换为CSV记录
     * 
     * @param comment 评论对象
     * @return CSV记录数组
     */
    public String[] commentToRecord(Comment comment) {
        String picUrls = comment.getPictures().stream()
                .map(Picture::getImgSrc)
                .collect(Collectors.joining(";"));
        
        return new String[]{
                comment.getBvid(),           // BV号
                comment.getUname(),          // 用户名
                comment.getSex(),            // 性别
                comment.getContent(),        // 评论内容
                picUrls,                     // 图片URL
                String.valueOf(comment.getRpid()),      // 评论ID
                String.valueOf(comment.getOid()),       // 评论区ID
                String.valueOf(comment.getMid()),       // 发送者ID
                String.valueOf(comment.getParent()),    // 父评论ID
                String.valueOf(comment.getFansgrade()), // 是否粉丝
                String.valueOf(comment.getCtime()),     // 评论时间戳
                String.valueOf(comment.getLike()),      // 点赞数
                String.valueOf(comment.isFollowing()), // 是否关注
                String.valueOf(comment.getCurrentLevel()), // 当前等级
                comment.getLocation()        // 位置
        };
    }
    
    /**
     * 保存评论到CSV文件
     * 
     * @param filename BV号
     * @param comments 评论列表
     * @param outputDir 输出目录
     * @param title 视频标题，如果提供则用于日志显示
     * @param overwrite 是否覆盖现有文件，true时会清空现有数据重新写入
     */
    public void saveToCsv(String filename, List<Comment> comments, String outputDir, 
                         String title, boolean overwrite) {
        if (comments == null || comments.isEmpty()) {
            return;
        }
        
        // 获取配置以决定是否下载图片
        boolean shouldDownloadImages = defaultConfiguration.defaultDownloadImage;
        
        // 确保输出目录存在
        Path outputPath = Paths.get(outputDir);
        try {
            Files.createDirectories(outputPath);
        } catch (IOException e) {
            logger.error("创建输出目录失败: {}", e.getMessage());
            return;
        }
        
        // CSV文件路径
        Path csvPath = outputPath.resolve(filename + ".csv");
        
        // 用于日志显示的名称
        String displayName = title != null ? String.format("%s (%s)", filename, title) : filename;
        
        // 判断是否需要创建新文件或覆盖
        boolean createNewFile = !Files.exists(csvPath) || overwrite;
        
        if (createNewFile) {
            // 创建新文件或覆盖现有文件
            try (FileWriter fileWriter = new FileWriter(csvPath.toFile(), StandardCharsets.UTF_8,false);
                 CSVWriter csvWriter = new CSVWriter(fileWriter)) {
                
                // 写入表头
                String[] headers = {
                    "bvid",
                    "upname", 
                    "sex",
                    "content",
                    "pictures",
                    "rpid",
                    "oid",
                    "mid",
                    "parent",
                    "fans_grade",
                    "ctime",
                    "like",
                    "following",
                    "level",
                    "location"
                };
                csvWriter.writeNext(headers);
                
                // 写入评论
                int validComments = 0;
                int downloadedImages = 0;
                
                for (Comment comment : comments) {
                    if (comment.getUname() == null || comment.getUname().isEmpty()) {
                        continue;
                    }
                    
                    // 根据配置决定是否下载图片
                    if (shouldDownloadImages && comment.getPictures() != null && !comment.getPictures().isEmpty()) {
                        imageDownloader.downloadImages(
                            comment.getUname(), 
                            comment.getPictures(), 
                            outputPath.resolve("images").toString()
                        );
                        downloadedImages += comment.getPictures().size();
                    }
                    
                    // 写入评论
                    String[] record = commentToRecord(comment);
                    csvWriter.writeNext(record);
                    validComments++;
                }
                
                String action = overwrite ? "覆盖写入" : "创建并写入";
                logger.info("成功{} {} 条评论到 {}", action, validComments, displayName);
                
                if (shouldDownloadImages && downloadedImages > 0) {
                    logger.info("已下载 {} 张图片", downloadedImages);
                } else if (!shouldDownloadImages) {
                    logger.info("已跳过图片下载（可在设置中启用或使用【获取图片】按钮）");
                }
                
            } catch (IOException e) {
                logger.error("{}CSV文件失败: {}", (overwrite ? "覆盖" : "创建"), e.getMessage());
            }
        } else {
            // 追加到现有文件
            try (FileWriter fileWriter = new FileWriter(csvPath.toFile(), StandardCharsets.UTF_8, true);
                 CSVWriter csvWriter = new CSVWriter(fileWriter)) {
                
                int validComments = 0;
                int downloadedImages = 0;
                
                for (Comment comment : comments) {
                    if (comment.getUname() == null || comment.getUname().isEmpty()) {
                        continue;
                    }
                    
                    // 根据配置决定是否下载图片
                    if (shouldDownloadImages && comment.getPictures() != null && !comment.getPictures().isEmpty()) {
                        imageDownloader.downloadImages(
                            comment.getUname(), 
                            comment.getPictures(), 
                            outputPath.resolve("images").toString()
                        );
                        downloadedImages += comment.getPictures().size();
                    }
                    
                    // 写入评论
                    String[] record = commentToRecord(comment);
                    csvWriter.writeNext(record);
                    validComments++;
                }
                
                logger.info("成功追加 {} 条评论到 {}", validComments, displayName);
                
                if (shouldDownloadImages && downloadedImages > 0) {
                    logger.info("已下载 {} 张图片", downloadedImages);
                } else if (!shouldDownloadImages) {
                    logger.info("已跳过图片下载（可在设置中启用或使用【获取图片】按钮）");
                }
                
            } catch (IOException e) {
                logger.error("追加CSV文件失败: {}", e.getMessage());
            }
        }
    }
    
    /**
     * 重载方法，提供默认参数
     */
    public void saveToCsv(String filename, List<Comment> comments, String outputDir) {
        saveToCsv(filename, comments, outputDir, null, false);
    }
    
    /**
     * 重载方法，提供默认参数
     */
    public void saveToCsv(String filename, List<Comment> comments, String outputDir, String title) {
        saveToCsv(filename, comments, outputDir, title, false);
    }
}